home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 32
/
Amiga Format AFCD32 (Nov 1998, Issue 117).iso
/
-seriously_amiga-
/
programming
/
c
/
mesa-2.6
/
src
/
amigamesartl.c
next >
Wrap
C/C++ Source or Header
|
1998-08-10
|
31KB
|
1,219 lines
/*
* Mesa 3-D graphics library
* Version: 2.3
* Copyright (C) 1995-1997 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* amigamesartl.c
*
* Version 1.0 27 Jun 1998
* by Jarno van der Linden
* jarno@kcbbs.gen.nz
*
* Based on ddsample.c ver 1.5
*
* Version 1.1 02 Aug 1998
* by Jarno van der Linden
* jarno@kcbbs.gen.nz
*
* - Fixed several bugs in glClear()
* - QUICKLOOP macros added
* - Noticed that { *x = p; x++; } is faster than { *x++ = p; }
* - Quantizer changed to plugin library
* - Use environment variables to select quantizer
*
*/
/*
* This is a sample template for writing new Mesa device drivers.
* You'll have to rewrite all the pseudo code below.
*
* Let's say you're interfacing Mesa to a window/operating system
* called FOO. Replace all occurances of FOOMesa with the real name
* you select for your interface (i.e. XMesa, WMesa, AmigaMesa).
*
* You'll have to design an API for clients to use, defined in a
* header called Mesa/include/GL/FooMesa.h Use the sample as an
* example. The API should at least have functions for creating
* rendering contexts, binding rendering contexts to windows/frame
* buffers, etc.
*
* Next, you'll have to write implementations for the device driver
* functions described in dd.h
*
* Note that you'll usually have to flip Y coordinates since Mesa's
* window coordinates start at the bottom and increase upward. Most
* window system's Y-axis increases downward
*
* Functions marked OPTIONAL may be completely omitted by your driver.
*
* Your Makefile should compile this module along with the rest of
* the core Mesa library.
*/
#include <stdlib.h>
#include "GL/amigamesartl.h"
#include "context.h"
#include "depth.h"
#include "macros.h"
#include "matrix.h"
#include "types.h"
#include "vb.h"
#include "gl/quantizer.h"
#include <intuition/intuition.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <m68881.h>
#define RGBA(r,g,b,a) (((r)<<24) | ((g)<<16) | ((b)<<8) | (a))
#define WINWIDTH(w) ((w)->Width - (w)->BorderLeft - (w)->BorderRight)
#define WINHEIGHT(w) ((w)->Height - (w)->BorderTop - (w)->BorderBottom)
#define QUICKLOOP16(n,l) { register int ql_var; \
for(ql_var=0; ql_var<((n) & 15); ql_var++) \
{ l; }\
for(; ql_var<(n); ql_var+=16) \
{ l; l; l; l; l; l; l; l; l; l; l; l; l; l; l; l; } \
}
#define QUICKLOOP8(n,l) { register int ql_var; \
for(ql_var=0; ql_var<((n) & 7); ql_var++) \
{ l; }\
for(; ql_var<(n); ql_var+=8) \
{ l; l; l; l; l; l; l; l; } \
}
#define QUICKLOOP4(n,l) { register int ql_var; \
for(ql_var=0; ql_var<((n) & 3); ql_var++) \
{ l; }\
for(; ql_var<(n); ql_var+=4) \
{ l; l; l; l; } \
}
#define QUICKLOOP2(n,l) { register int ql_var; \
for(ql_var=0; ql_var<((n) & 1); ql_var++) \
{ l; }\
for(; ql_var<(n); ql_var+=2) \
{ l; l; } \
}
#define QUICKLOOP1(n,l) { register int ql_var; \
for(ql_var=0; ql_var<(n); ql_var++) \
{ l; } \
}
/*
* This struct contains all device-driver state information. Think of it
* as an extension of the core GLcontext from types.h.
*/
struct amiga_mesa_rtl_context {
GLcontext *gl_ctx; /* the core library context */
GLvisual *gl_visual;
GLframebuffer *gl_buffer; /* The depth, stencil, accum, etc buffers */
GLboolean rgb_flag; /* RGB mode? */
struct Window *the_window; /* Window pointer */
struct DrawInfo *di; /* DrawInfo pointer for screen info */
unsigned long *buffer; /* The image buffer */
GLint width, height; /* Size of image buffer */
GLint wwidth, wheight; /* Window width and height */
unsigned long pixel; /* current color index or RGBA pixel value */
unsigned long clearpixel; /* pixel for clearing the color buffers */
unsigned long numcolours; /* Number of colours to use for this context */
unsigned long colourbase; /* First colour table index */
struct Library *quantizer; /* Quantizer library */
char qname[48]; /* Name of quantizer */
ULONG qver; /* Version of quantizer */
/* etc... */
};
static AmigaMesaRTLContext Current = NULL;
static struct Library *quantizerBase = NULL;
static const char *renderer_string(void)
{
return "AmigaMesaRTL";
}
static void clear_index( GLcontext *ctx, GLuint index )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* implement glClearIndex */
/* usually just save the color index value in the amesartl struct */
amesartl->clearpixel = amesartl->colourbase + index;
}
static void clear_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* implement glClearColor */
/* color components are floats in [0,1] */
/* usually just save the value in the amesartl struct */
amesartl->clearpixel = RGBA(r,g,b,a);
}
static void clear( GLcontext *ctx,
GLboolean all, GLint x, GLint y, GLint width, GLint height )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
unsigned long *bp;
unsigned char *bbp;
unsigned long p;
/*
* Clear the specified region of the current color buffer using the clear
* color or index as specified by one of the two functions above.
* If all==GL_TRUE, clear whole buffer, else just clear region defined
* by x,y,width,height
*/
p = amesartl->clearpixel;
y = amesartl->wheight-1-y;
if(amesartl->rgb_flag)
{
if(all)
{
bp = amesartl->buffer;
QUICKLOOP16(amesartl->width*amesartl->height,
{
*bp = p;
bp++;
}
)
}
else
{
bp = amesartl->buffer+y*amesartl->width+x;
QUICKLOOP16(height,
{
QUICKLOOP16(width,
{
*bp = p;
bp++;
}
)
bp -= amesartl->width + width;
}
)
}
}
else
{
if(all)
{
memset(amesartl->buffer, p, amesartl->width * amesartl->height);
}
else
{
bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
QUICKLOOP16(height,
{
memset(bbp, p, width);
bbp -= amesartl->width;
}
)
}
}
}
static void set_index( GLcontext *ctx, GLuint index )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* Set the current color index. */
amesartl->pixel = amesartl->colourbase + index;
}
static void set_color( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* Set the current RGBA color. */
/* r is in [0,ctx->Visual->RedScale] */
/* g is in [0,ctx->Visual->GreenScale] */
/* b is in [0,ctx->Visual->BlueScale] */
/* a is in [0,ctx->Visual->AlphaScale] */
amesartl->pixel = RGBA(r,g,b,a);
}
static GLboolean set_buffer( GLcontext *ctx, GLenum mode )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* set the current drawing/reading buffer, return GL_TRUE or GL_FALSE */
/* for success/failure */
if (mode==GL_FRONT)
{
return GL_TRUE;
}
else
{
return GL_FALSE;
}
}
static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* return the width and height of the current buffer */
/* if anything special has to been done when the buffer/window is */
/* resized, do it now */
GLuint rw,rh;
*width = amesartl->wwidth = WINWIDTH(amesartl->the_window);
*height = amesartl->wheight = WINHEIGHT(amesartl->the_window);
rw = (((amesartl->wwidth + 15)>>4)<<4);
rh = amesartl->wheight;
if((rw != amesartl->width) || (rh != amesartl->height))
{
if(amesartl->buffer) free(amesartl->buffer);
amesartl->buffer = NULL;
amesartl->width = rw;
amesartl->height = rh;
amesartl->buffer = calloc(amesartl->width * amesartl->height, amesartl->rgb_flag ? sizeof(unsigned long) : sizeof(unsigned char));
quantizerBase = amesartl->quantizer;
ResizeQuantizer(amesartl->width,amesartl->height);
}
}
static void write_color_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLubyte red[], const GLubyte green[],
const GLubyte blue[], const GLubyte alpha[],
const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
unsigned long *bp;
const GLubyte *ri,*gi,*bi,*ai,*mi;
y = amesartl->wheight-1-y;
bp = amesartl->buffer+y*amesartl->width+x;
ri = red;
gi = green;
bi = blue;
ai = alpha;
mi = mask;
if (mask)
{
QUICKLOOP1(n,
{
if (*mi)
*bp = RGBA(*ri,*gi,*bi,*ai);
mi++;
bp++;
ri++;
gi++;
bi++;
ai++;
}
)
}
else
{
QUICKLOOP1(n,
{
*bp = RGBA(*ri,*gi,*bi,*ai);
bp++;
ri++;
gi++;
bi++;
ai++;
}
)
}
}
static void write_monocolor_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLubyte mask[])
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
unsigned long *bp;
const GLubyte *mi;
unsigned long p;
y = amesartl->wheight-1-y;
bp = amesartl->buffer+y*amesartl->width+x;
mi = mask;
p = amesartl->pixel;
QUICKLOOP1(n,
{
if (*mi)
*bp = p;
mi++;
bp++;
}
)
}
static void write_color_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
const GLubyte r[], const GLubyte g[],
const GLubyte b[], const GLubyte a[],
const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const GLubyte *ri,*gi,*bi,*ai,*mi;
const GLint *xi,*yi;
ri = r;
gi = g;
bi = b;
ai = a;
mi = mask;
xi = x;
yi = y;
QUICKLOOP1(n,
{
if (*mi)
*(amesartl->buffer + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = RGBA(*ri,*gi,*bi,*ai);
mi++;
ri++;
gi++;
bi++;
ai++;
xi++;
yi++;
}
)
}
static void write_monocolor_pixels( GLcontext *ctx,
GLuint n,
const GLint x[], const GLint y[],
const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const GLubyte *mi;
const GLint *xi,*yi;
unsigned long p;
mi = mask;
xi = x;
yi = y;
p = amesartl->pixel;
QUICKLOOP1(n,
{
if (*mi)
*(amesartl->buffer + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = p;
mi++;
xi++;
yi++;
}
)
}
static void write_index_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
const GLuint index[],
const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
unsigned char *bbp;
const GLuint *ii;
const GLubyte *mi;
const unsigned long base = amesartl->colourbase;
y = amesartl->wheight-1-y;
bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
ii = index;
mi = mask;
QUICKLOOP1(n,
{
if (*mi)
*bbp = *ii + base;
mi++;
bbp++;
ii++;
}
)
}
static void write_monoindex_span( GLcontext *ctx,
GLuint n,GLint x,GLint y,const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
unsigned char *bbp;
unsigned long p;
const GLubyte *mi;
y = amesartl->wheight-1-y;
bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
mi = mask;
p = amesartl->pixel;
QUICKLOOP1(n,
{
if (*mi)
*bbp = p;
mi++;
bbp++;
}
)
}
static void write_index_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
const GLuint index[], const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const GLuint *ii;
const GLubyte *mi;
const GLint *xi,*yi;
const unsigned long base = amesartl->colourbase;
ii = index;
mi = mask;
xi = x;
yi = y;
QUICKLOOP1(n,
{
if (*mi)
*(((unsigned char *)amesartl->buffer) + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = *ii + base;
mi++;
ii++;
xi++;
yi++;
}
)
}
static void write_monoindex_pixels( GLcontext *ctx,
GLuint n,
const GLint x[], const GLint y[],
const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
unsigned long p;
const GLubyte *mi;
const GLint *xi,*yi;
p = amesartl->pixel;
mi = mask;
xi = x;
yi = y;
QUICKLOOP1(n,
{
if (*mi)
*(((unsigned char *)amesartl->buffer) + (amesartl->wheight-1-*yi) * amesartl->width + *xi) = p;
mi++;
xi++;
yi++;
}
)
}
static void read_index_span( GLcontext *ctx,
GLuint n, GLint x, GLint y, GLuint index[])
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const unsigned char *bbp;
GLuint *ii;
const unsigned long base = amesartl->colourbase;
y = amesartl->wheight-1-y;
bbp = ((unsigned char *)amesartl->buffer)+y*amesartl->width+x;
ii = index;
QUICKLOOP1(n,
{
*ii = *bbp - base;
ii++;
bbp++;
}
)
}
static void read_color_span( GLcontext *ctx,
GLuint n, GLint x, GLint y,
GLubyte red[], GLubyte green[],
GLubyte blue[], GLubyte alpha[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const unsigned char *bbp;
GLubyte *ri,*gi,*bi,*ai;
y = amesartl->wheight-1-y;
bbp = (unsigned char *)(amesartl->buffer+y*amesartl->width+x);
ri = red;
gi = green;
bi = blue;
ai = alpha;
QUICKLOOP1(n,
{
*ri = *bbp;
ri++;
bbp++;
*gi = *bbp;
gi++;
bbp++;
*bi = *bbp;
bi++;
bbp++;
*ai = *bbp;
ai++;
bbp++;
}
)
}
static void read_index_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLuint indx[], const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const GLint *xi,*yi;
GLuint *ii;
const GLubyte *mi;
const unsigned long base = amesartl->colourbase;
ii = indx;
xi = x;
yi = y;
mi = mask;
QUICKLOOP1(n,
{
if(*mi)
*ii = *(((unsigned char *)amesartl->buffer) + (amesartl->wheight-1-*yi) * amesartl->width + *xi) - base;
mi++;
xi++;
yi++;
ii++;
}
)
}
static void read_color_pixels( GLcontext *ctx,
GLuint n, const GLint x[], const GLint y[],
GLubyte red[], GLubyte green[],
GLubyte blue[], GLubyte alpha[],
const GLubyte mask[] )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
const unsigned char *bbp;
GLubyte *ri,*gi,*bi,*ai;
const GLint *xi,*yi;
const GLubyte *mi;
ri = red;
gi = green;
bi = blue;
ai = alpha;
xi = x;
yi = y;
mi = mask;
QUICKLOOP1(n,
{
if(*mi)
{
bbp = (unsigned char *)(amesartl->buffer + (amesartl->wheight-1-*yi) *amesartl->width + *xi);
*ri = *bbp;
bbp++;
*gi = *bbp;
bbp++;
*bi = *bbp;
bbp++;
*ai = *bbp;
bbp++;
}
mi++;
ri++;
gi++;
bi++;
ai++;
xi++;
yi++;
}
)
}
static void finish( GLcontext *ctx )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* OPTIONAL FUNCTION: implements glFinish if possible */
}
static void flush( GLcontext *ctx )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* OPTIONAL FUNCTION: implements glFlush if possible */
/* OK. The big one. Dump the buffer to the window */
/* See if the window is the size we expect it to be. */
/* If not, better not do anything, we might write into non-existent */
/* window space. We expect a redraw soon anyway. */
if((WINWIDTH(amesartl->the_window) != amesartl->wwidth) ||
(WINHEIGHT(amesartl->the_window) != amesartl->wheight))
return;
quantizerBase = amesartl->quantizer;
Quantize(amesartl->buffer);
}
static GLboolean index_mask( GLcontext *ctx, GLuint mask )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* OPTIONAL FUNCTION: implement glIndexMask if possible, else
* return GL_FALSE
*/
return(GL_FALSE);
}
static GLboolean color_mask( GLcontext *ctx,
GLboolean rmask, GLboolean gmask,
GLboolean bmask, GLboolean amask)
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* OPTIONAL FUNCTION: implement glColorMask if possible, else
* return GL_FALSE
*/
return(GL_FALSE);
}
static GLboolean logicop( GLcontext *ctx, GLenum op )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/*
* OPTIONAL FUNCTION:
* Implements glLogicOp if possible. Return GL_TRUE if the device driver
* can perform the operation, otherwise return GL_FALSE. If GL_FALSE
* is returned, the logic op will be done in software by Mesa.
*/
return(GL_FALSE);
}
static void dither( GLcontext *ctx, GLboolean enable )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* OPTIONAL FUNCTION: enable/disable dithering if applicable */
}
static void error( GLcontext *ctx )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
/* OPTIONAL FUNCTION: catch error */
}
/**********************************************************************/
/***** Optimized triangle rendering *****/
/**********************************************************************/
/* (Based on osmesa.c) */
/*
* Smooth-shaded, z triangle, RGBA color.
*/
static void smooth_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
GLuint v2, GLuint pv )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
#define INTERP_Z 1
#define INTERP_RGB 1
#define INTERP_ALPHA 1
#define INNER_LOOP( LEFT, RIGHT, Y ) \
{ \
const GLint len = RIGHT-LEFT; \
unsigned long *bp; \
GLdepth *zr = zRow; \
GLdepth z; \
bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT; \
QUICKLOOP1(len, \
{ \
z = FixedToDepth(ffz); \
if (z < *zr) { \
*zr = z; \
*bp = RGBA(FixedToInt(ffr), FixedToInt(ffg), \
FixedToInt(ffb), FixedToInt(ffa) ); \
} \
ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; ffa += fdadx; \
ffz += fdzdx; \
bp++; \
zr++; \
} \
) \
}
#include "tritemp.h"
}
/*
* Flat-shaded, z triangle, RGBA color.
*/
static void flat_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
GLuint v2, GLuint pv )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
#define INTERP_Z 1
#define SETUP_CODE \
GLubyte r = VB->Color[pv][0]; \
GLubyte g = VB->Color[pv][1]; \
GLubyte b = VB->Color[pv][2]; \
GLubyte a = VB->Color[pv][3]; \
unsigned long p = RGBA(r,g,b,a);
#define INNER_LOOP( LEFT, RIGHT, Y ) \
{ \
const GLint len = RIGHT-LEFT; \
unsigned long *bp; \
GLdepth *zr = zRow; \
GLdepth z; \
bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT; \
QUICKLOOP1(len, \
{ \
z = FixedToDepth(ffz); \
if (z < *zr) { \
*zr = z; \
*bp = p; \
} \
ffz += fdzdx; \
bp++; \
zr++; \
} \
) \
}
#include "tritemp.h"
}
/*
* Smooth-shaded, z-less triangle, RGBA color.
*/
static void smooth_color_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
GLuint v2, GLuint pv )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
#define INTERP_RGB 1
#define INTERP_ALPHA 1
#define INNER_LOOP( LEFT, RIGHT, Y ) \
{ \
const GLint len = RIGHT-LEFT; \
unsigned long *bp; \
bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT; \
QUICKLOOP1(len, \
{ \
*bp = RGBA(FixedToInt(ffr), FixedToInt(ffg), \
FixedToInt(ffb), FixedToInt(ffa) ); \
ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; ffa += fdadx; \
bp++; \
} \
) \
}
#include "tritemp.h"
}
/*
* Flat-shaded, z triangle, RGBA color.
*/
static void flat_color_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
GLuint v2, GLuint pv )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
#define SETUP_CODE \
GLubyte r = VB->Color[pv][0]; \
GLubyte g = VB->Color[pv][1]; \
GLubyte b = VB->Color[pv][2]; \
GLubyte a = VB->Color[pv][3]; \
unsigned long p = RGBA(r,g,b,a);
#define INNER_LOOP( LEFT, RIGHT, Y ) \
{ \
const GLint len = RIGHT-LEFT; \
unsigned long *bp; \
bp = amesartl->buffer+(amesartl->wheight-1-Y)*amesartl->width+LEFT; \
QUICKLOOP1(len, \
{ \
*bp = p; \
bp++; \
} \
) \
}
#include "tritemp.h"
}
/*
* Return pointer to an accelerated triangle function if possible.
*/
static triangle_func choose_triangle_function( GLcontext *ctx )
{
struct amiga_mesa_rtl_context *amesartl = (struct amiga_mesa_rtl_context *) ctx->DriverCtx;
if(amesartl->rgb_flag == GL_FALSE)
return NULL;
if (ctx->Polygon.SmoothFlag) return NULL;
if (ctx->Polygon.StippleFlag) return NULL;
if (ctx->Texture.Enabled) return NULL;
if (ctx->RasterMask==DEPTH_BIT
&& ctx->Depth.Func==GL_LESS
&& ctx->Depth.Mask==GL_TRUE)
{
if (ctx->Light.ShadeModel==GL_SMOOTH) {
return smooth_color_z_triangle;
}
else
{
return flat_color_z_triangle;
}
}
else if(ctx->RasterMask==0)
{
if (ctx->Light.ShadeModel==GL_SMOOTH) {
return smooth_color_triangle;
}
else
{
return flat_color_triangle;
}
}
return NULL;
}
/**********************************************************************/
/**********************************************************************/
static void setup_DD_pointers( GLcontext *ctx )
{
/* Initialize all the pointers in the DD struct. Do this whenever */
/* a new context is made current or we change buffers via set_buffer! */
ctx->Driver.RendererString = renderer_string;
ctx->Driver.UpdateState = setup_DD_pointers;
ctx->Driver.ClearIndex = clear_index;
ctx->Driver.ClearColor = clear_color;
ctx->Driver.Clear = clear;
ctx->Driver.Index = set_index;
ctx->Driver.Color = set_color;
ctx->Driver.SetBuffer = set_buffer;
ctx->Driver.GetBufferSize = get_buffer_size;
/* Pixel/span writing functions: */
ctx->Driver.WriteColorSpan = write_color_span;
ctx->Driver.WriteMonocolorSpan = write_monocolor_span;
ctx->Driver.WriteColorPixels = write_color_pixels;
ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
ctx->Driver.WriteIndexSpan = write_index_span;
ctx->Driver.WriteMonoindexSpan = write_monoindex_span;
ctx->Driver.WriteIndexPixels = write_index_pixels;
ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
/* Pixel/span reading functions: */
ctx->Driver.ReadIndexSpan = read_index_span;
ctx->Driver.ReadColorSpan = read_color_span;
ctx->Driver.ReadIndexPixels = read_index_pixels;
ctx->Driver.ReadColorPixels = read_color_pixels;
ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
/*
* OPTIONAL FUNCTIONS: these may be left uninitialized if the device
* driver can't/needn't implement them.
*/
ctx->Driver.Flush = flush;
#if 0
ctx->Driver.Finish = finish;
ctx->Driver.IndexMask = index_mask;
ctx->Driver.ColorMask = color_mask;
ctx->Driver.LogicOp = logicop;
ctx->Driver.Dither = dither;
ctx->Driver.Error = error;
ctx->Driver.NearFar = near_far;
#endif
}
/**********************************************************************/
/***** FOO/Mesa API Functions *****/
/**********************************************************************/
__asm __saveds AmigaMesaRTLContext AmigaMesaRTLCreateContextA( register __a0 struct Window *window, register __a1 struct TagItem *tags )
{
AmigaMesaRTLContext c;
GLboolean rgb_flag, alpha_flag, db_flag;
GLint depth_bits, stencil_bits, accum_bits, index_bits;
GLfloat red_scale, green_scale, blue_scale, alpha_scale;
GLint red_bits, green_bits, blue_bits, alpha_bits;
int maxnumcolours;
char *strp,str[32];
c = (AmigaMesaRTLContext) calloc( 1, sizeof(struct amiga_mesa_rtl_context) );
if (!c)
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
rgb_flag = GetTagData(AMRTL_RGBAMode, (ULONG)TRUE, tags) ? GL_TRUE : GL_FALSE;
rgb_flag = GetTagData(AMRTL_IndexMode, (ULONG)FALSE, tags) ? GL_FALSE : rgb_flag;
if(rgb_flag)
{
/* RGB(A) mode */
alpha_flag = GL_FALSE;
db_flag = GL_FALSE;
depth_bits = DEPTH_BITS;
stencil_bits = STENCIL_BITS;
accum_bits = ACCUM_BITS;
index_bits = 0;
red_scale = 255.0;
green_scale = 255.0;
blue_scale = 255.0;
alpha_scale = 255.0;
red_bits = 8;
green_bits = 8;
blue_bits = 8;
alpha_bits = 0;
}
else
{
/* color index mode */
alpha_flag = GL_FALSE;
db_flag = GL_FALSE;
depth_bits = DEPTH_BITS;
stencil_bits = STENCIL_BITS;
accum_bits = ACCUM_BITS;
index_bits = 8;
red_scale = 0.0;
green_scale = 0.0;
blue_scale = 0.0;
alpha_scale = 0.0;
red_bits = 8;
green_bits = 8;
blue_bits = 8;
alpha_bits = 0;
}
/* Create core visual */
c->gl_visual = gl_create_visual( rgb_flag,
alpha_flag,
db_flag,
depth_bits,
stencil_bits,
accum_bits,
index_bits,
red_scale, green_scale, blue_scale, alpha_scale,
red_bits, green_bits, blue_bits, alpha_bits );
if(!c->gl_visual)
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
c->gl_ctx = gl_create_context( c->gl_visual,
NULL,
(void *) c );
if(!c->gl_ctx)
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
c->gl_buffer = gl_create_framebuffer( c->gl_visual );
if(!c->gl_buffer)
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
c->rgb_flag = rgb_flag;
c->the_window = window;
c->di = GetScreenDrawInfo(c->the_window->WScreen);
if(!c->di)
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
c->buffer = NULL;
c->width = 0;
c->height = 0;
c->wwidth = WINWIDTH(c->the_window);
c->wheight = WINHEIGHT(c->the_window);
c->pixel = 0;
c->clearpixel = 0;
maxnumcolours = 1L<<c->di->dri_Depth;
c->numcolours = GetTagData(AMRTL_NumColours, maxnumcolours, tags);
c->colourbase = GetTagData(AMRTL_ColourBase, (ULONG)0, tags);
if(c->colourbase > (maxnumcolours-2))
c->colourbase = maxnumcolours-2;
if(c->colourbase < 0)
c->colourbase = 0;
if((c->colourbase + c->numcolours) > maxnumcolours)
{
c->numcolours = maxnumcolours-c->colourbase;
}
if(c->numcolours < 2)
c->numcolours = 2;
strcpy(c->qname,"quantizers/");
if(GetVar("AmigaMesaRTL/Quantizer",str,32,0) == -1)
strcpy(str,"dl1");
strp = (char *)GetTagData(AMRTL_Quantizer, NULL, tags);
if(strp)
{
strncpy(str,strp,32);
str[31] = '\0';
}
strcat(c->qname,str);
c->qver = 0;
if(GetVar("AmigaMesaRTL/QuantizerVersion",str,32,0) != -1)
c->qver = atol(str);
c->qver = GetTagData(AMRTL_QuantizerVersion, c->qver, tags);
c->quantizer = OpenLibrary(c->qname,c->qver);
if(!c->quantizer)
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
quantizerBase = c->quantizer;
if(!InitQuantizer(window, rgb_flag ? AMRTL_RGBAMode : AMRTL_IndexMode, c->numcolours, c->colourbase))
{
AmigaMesaRTLDestroyContext( c );
return NULL;
}
return c;
}
__asm __saveds void AmigaMesaRTLDestroyContext( register __a0 AmigaMesaRTLContext c )
{
if(c)
{
if(c->quantizer)
{
quantizerBase = c->quantizer;
DeleteQuantizer();
CloseLibrary(c->quantizer);
}
if(c->di) FreeScreenDrawInfo(c->the_window->WScreen, c->di);
c->di = NULL;
if(c->gl_buffer) gl_destroy_framebuffer( c->gl_buffer );
c->gl_buffer = NULL;
if(c->gl_ctx) gl_destroy_context( c->gl_ctx );
c->gl_ctx = NULL;
if(c->gl_visual) gl_destroy_visual( c->gl_visual );
c->gl_visual = NULL;
if(c->buffer) free(c->buffer);
c->buffer = NULL;
free(c);
}
c = NULL;
}
/*
* Make the specified context the current one
* Might also want to specify the window/drawable here, like for GLX.
*/
__asm __saveds void AmigaMesaRTLMakeCurrent( register __a0 AmigaMesaRTLContext c )
{
gl_make_current( c->gl_ctx, c->gl_buffer );
setup_DD_pointers( c->gl_ctx );
gl_Viewport( c->gl_ctx, 0, 0, c->wwidth, c->wheight );
Current = c;
}
__asm __saveds AmigaMesaRTLContext AmigaMesaRTLGetCurrentContext( void )
{
return Current;
}
/* you may need to add other FOO/Mesa functions too... */